package practica1;

public abstract class Funcion {
	
	protected double xMin;
	protected double xMax;
	protected double precision;
	protected int longCromo;
	protected double maximo;
	
	abstract public double [] calcFenotipo(boolean [] genes);
	abstract public double calcAptitud(double [] fenotipo);	
	
	public Funcion(double min, double max, double p){
		xMin = min;
		xMax = max;
		precision = p;
		longCromo = ((int)(Math.ceil((Math.log(1+((xMax-xMin)/precision)))/Math.log(2))));
	}	
	
	public int getLongCromo() {
		return longCromo;
	}
	
	public double getXmin(){
		return xMin;
	}
	
	public double getXmax(){
		return xMax;
	}
	
	static public boolean[] gray2Bin(boolean[] gray){
		boolean[] bin = new boolean[gray.length+1];
		boolean[] bin2 = new boolean[gray.length];
		bin[0] = false;
		for(int i=1;i<=gray.length;i++){
			bin[i] = bin[i-1] ^ gray[i-1];
			bin2[i-1] = bin[i];
		}
		return bin2;
	}
	
	static public int bin2Dec(boolean [] genes){
		int valor = 0; 
		for(int i=0;i<genes.length;i++){
			if(genes[i])
				valor = (int) (valor + Math.pow(2, genes.length-i-1));
		}
		return valor;
	}
	
	static public int gray2Dec(boolean[] genes){
		boolean[] genesBin = gray2Bin(genes);
		return bin2Dec(genesBin);
	}
	
	public void evaluarCromosoma(Cromosoma c){
		boolean[] g = c.getGenotipo();
		c.setFenotipo(calcFenotipo(g));
		c.setAptitud(calcAptitud(c.getFenotipo()));
	}
	
	public double calcFenotipo(boolean [] genes, double min, double max, double longitud) {
		//return min + Funcion.gray2Dec(genes) * (max-min)/(Math.pow(2,longitud)-1);
		return min + Funcion.bin2Dec(genes) * (max-min)/(Math.pow(2,longitud)-1);
	}
	
	public double calcAptitud(boolean[] genes) {
		return calcAptitud(calcFenotipo(genes));
	}
	
	public boolean maximoAprox(double x){
		int suelo, techo;
		suelo = (int)Math.floor(maximo);
		techo = (int)Math.ceil(maximo);
		return suelo <= x && x <= techo;
	}
	
}
